Problem s strlower()

Otázka od: Vymazal Milan

12. 11. 2002 15:49

Zdravim

mam takovej zvlastni problem, asi to bude moji blbosti ale nevim si s
necim rady. Mam v programu kousek kodu ktere ze seznamu souboru
provede trideni. pokud ma soubor koncovku .sa tak ho hodi do satemp a
pokud ne tak do recordtempu. Jenze proto abych overil tu priponu potrebuji
ten zaznam prevest na mala pismena. to delam v promene radek.

var
  satemp,recordtemp:TStringList;
begin
  SaTemp:=TStringList.create;
  RecordTemp:=TStringLIst.create;

  FindFile.Directory:=datapath;
  FindFile.Filter:='*.*';
  FindFile.Recurse:=true;
  FindFile.Execute;

  for i:=0 to FindFile.Files.Count-1 do
  begin
    radek:=(findfile.files[i]);
    d('1'+findfile.files[i]);

    // v teto casti mi to vypise findfiles.files[i] s nezmenenejma
    pismenama to je ok.


                                 
    strlower(pchar(radek));
    d('2'+findfile.files[i]); << tady to vypise vsechno maly ??

    // tady uz jsou vsechna pismena mala ? ale proc vzdyt uz s
    findfile.files[i] nepracuji ? Nepotrebuji aby to bylo male
    potrebuji aby to bylo s originalni velikosti
    
    

    if extractfileext(radek)='.sa' then
    Satemp.Add(findfile.files[i])
    else RecordTemp.Add(findfile.files[i]);
  end;

Odpovedá: ing. Jan Fiala

12. 11. 2002 13:42

protoze Radek je PChar a to je jen ukazatel na retezec. Takze pokud
pracujes s Radek, provadis to vlastne i s tim puvodnim retezcem.

--
ing. Jan Fiala
mailto:jan.fiala@iol.cz

12.11.2002 Vymazal Milan:
> Zdravim

> mam takovej zvlastni problem, asi to bude moji blbosti ale nevim si s
> necim rady. Mam v programu kousek kodu ktere ze seznamu souboru
> provede trideni. pokud ma soubor koncovku .sa tak ho hodi do satemp a
> pokud ne tak do recordtempu. Jenze proto abych overil tu priponu potrebuji
> ten zaznam prevest na mala pismena. to delam v promene radek.

> var
> satemp,recordtemp:TStringList;
> begin
> SaTemp:=TStringList.create;
> RecordTemp:=TStringLIst.create;

> FindFile.Directory:=datapath;
> FindFile.Filter:='*.*';
> FindFile.Recurse:=true;
> FindFile.Execute;

> for i:=0 to FindFile.Files.Count-1 do
> begin
> radek:=(findfile.files[i]);
> d('1'+findfile.files[i]);

> // v teto casti mi to vypise findfiles.files[i] s nezmenenejma
> pismenama to je ok.


                                 
> strlower(pchar(radek));
> d('2'+findfile.files[i]); << tady to vypise vsechno maly ??

> // tady uz jsou vsechna pismena mala ? ale proc vzdyt uz s
> findfile.files[i] nepracuji ? Nepotrebuji aby to bylo male
> potrebuji aby to bylo s originalni velikosti
    
    

> if extractfileext(radek)='.sa' then
> Satemp.Add(findfile.files[i])
> else RecordTemp.Add(findfile.files[i]);
> end;

Odpovedá: Ondrej Kelle

12. 11. 2002 14:15

> Mam v programu kousek kodu ktere ze seznamu souboru
> provede trideni. pokud ma soubor koncovku .sa tak ho hodi do satemp a
> pokud ne tak do recordtempu. Jenze proto abych overil tu
> priponu potrebuji
> ten zaznam prevest na mala pismena. to delam v promene radek.

Neviem, akeho typu je FindFile, ale predpokladam, ze TOpenDialog. V tom
pripade si narazil na reference counting dlhych stringov.

>
> for i:=0 to FindFile.Files.Count-1 do
> begin
> radek:=(findfile.files[i]);

radek ukazuje na ten isty retazec v pameti ako findfile.files[I], iba
refcount sa zvysil.

> d('1'+findfile.files[i]);
>
> // v teto casti mi to vypise findfiles.files[i] s nezmenenejma
> pismenama to je ok.
>
> strlower(pchar(radek));
> d('2'+findfile.files[i]); << tady to vypise vsechno maly ??

See above  

>
> // tady uz jsou vsechna pismena mala ? ale proc vzdyt uz s
> findfile.files[i] nepracuji ? Nepotrebuji aby to bylo male
> potrebuji aby to bylo s originalni velikosti
> if extractfileext(radek)='.sa' then
> Satemp.Add(findfile.files[i])
> else RecordTemp.Add(findfile.files[i]);
> end;

Najjednoduchsie bude podla mna vyhodit to volanie strlower a tu podmienku
napisat takto:
  if SameText(ExtractFileExt(radek), '.sa') then

kedze pre '.sa' nepotrebujes porovnavat podla locale. Inak by sa hodilo
AnsiCompareText.

HTH
TOndrej

Odpovedá: Dalibor Toman

12. 11. 2002 15:41

>
> Neviem, akeho typu je FindFile, ale predpokladam, ze TOpenDialog. V
tom
> pripade si narazil na reference counting dlhych stringov.
>
> >
> > for i:=0 to FindFile.Files.Count-1 do
> > begin
> > radek:=(findfile.files[i]);
>
> radek ukazuje na ten isty retazec v pameti ako findfile.files[I],
iba
> refcount sa zvysil.

rekl bych, ze ref count se nezmenil. Pokud je radek typu Pchar nema
smysl zvysovat
counter referenci, protoze kompilator stejne neni schopen na PChar
generovat kod pro automaticke uvolneni atd.

to prirazeni je ekvivalentni:
 pointervar := @stringvar[1]



D. Toman

Odpovedá: Ondrej Kelle

12. 11. 2002 17:36

> rekl bych, ze ref count se nezmenil. Pokud je radek typu Pchar nema
> smysl zvysovat counter referenci, protoze kompilator stejne neni
> schopen na PChar generovat kod pro automaticke uvolneni atd.

Mas pravdu v tom, ze z povodneho prispevku nebolo jasne, akeho typu je
premenna radek.  
Ja som automaticky predpokladal, ze je typu string, kvoli tomu typecastu na
PChar:

>> strlower(pchar(radek));

Kedze dnes som uz k celkovej entropii prispel dost, tu je jednoduchy
skompilovatelny priklad, ktory demonstruje to, co som mal na mysli:

procedure TForm1.Button1Click(Sender: TObject);
var
  I: Integer;
  S: string;
begin
  with OpenDialog1 do
    if Execute then
      for I := 0 to Files.Count - 1 do
      begin
        OutputDebugString(PChar(Files[I])); // povodny file name (mixed
case)
        S := Files[I];
        OutputDebugString(PChar(Format('Files[%d]: $%.8x, S: $%.8x', [I,
Integer(Pointer(Files[I])),
          Integer(Pointer(S))]))); // rovnake adresy
        StrLower(PChar(S));
        OutputDebugString(PChar(Files[I])); // zmeneny file name (lower
case)
      end;
end;

kde OpenDialog1 je typu TOpenDialog.

To, ze pri priradeni do premennej typu string sa zvysi refcount, sa da
zistit nejako takto:

// copied from System implementation
type
  PStrRec = ^StrRec;
  StrRec = packed record
    refCnt: Longint;
    length: Longint;
  end;

function StrRefCount(S: PChar): Integer;
var
  P: PStrRec;
begin
  P := PStrRec(Integer(S) - SizeOf(StrRec));
  Result := P^.refCnt;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  P: PChar;
  S: string;
begin
  with OpenDialog1 do
    if Execute then
    begin
      P := PChar(Files[0]);
      OutputDebugString(PChar(Format('P: $%.8x, refCnt: %d',
        [Integer(P), StrRefCount(P)])));

      // P: $00C22024, refCnt: 3

      // assignment by reference, increments refcount
      S := Files[0];
      
OutputDebugString(PChar(Format('P: $%.8x, refCnt: %d, S: $%.8x,
refCnt: %d',
        [Integer(P), StrRefCount(P), Integer(PChar(S)),
StrRefCount(PChar(S))])));

      // P: $00C22024, refCnt: 4, S: $00C22024, refCnt: 4

      // copy on demand: creates new string
      Delete(S, 1, 1);
      
OutputDebugString(PChar(Format('P: $%.8x, refCnt: %d, S: $%.8x,
refCnt: %d',
        [Integer(P), StrRefCount(P), Integer(PChar(S)),
StrRefCount(PChar(S))])));

      // P: $00C22024, refCnt: 3, S: $00C30070, refCnt: 1
    end;
end;

HTH
TOndrej

Odpovedá: Vymazal Milan

12. 11. 2002 14:57

Cau


iJF> protoze Radek je PChar a to je jen ukazatel na retezec. Takze pokud
iJF> pracujes s Radek, provadis to vlastne i s tim puvodnim retezcem.


aha. no nahradil jsem to lowercase. Ja jsem to rikal ze je to mo
debilitou.



--
Best regards,
 Vymazal mailto:vymazal.milan@seznam.cz

Odpovedá: Vymazal Milan

12. 11. 2002 14:57

Cau Ondrej,

Tuesday, November 12, 2002, 12:44:38 PM, you wrote:

>> Mam v programu kousek kodu ktere ze seznamu souboru
>> provede trideni. pokud ma soubor koncovku .sa tak ho hodi do satemp a
>> pokud ne tak do recordtempu. Jenze proto abych overil tu
>> priponu potrebuji
>> ten zaznam prevest na mala pismena. to delam v promene radek.

> Neviem, akeho typu je FindFile, ale predpokladam, ze TOpenDialog. V tom
> pripade si narazil na reference counting dlhych stringov.

ne ne FindFile je TStringList; Ale to je jedno to neres dal jsem tam
lowercase a vsechno je ready

>>
>> for i:=0 to FindFile.Files.Count-1 do
>> begin
>> radek:=(findfile.files[i]);

> radek ukazuje na ten isty retazec v pameti ako findfile.files[I], iba
> refcount sa zvysil.

>> d('1'+findfile.files[i]);
>>
>> // v teto casti mi to vypise findfiles.files[i] s nezmenenejma
>> pismenama to je ok.
>>
>> strlower(pchar(radek));
>> d('2'+findfile.files[i]); << tady to vypise vsechno maly ??

> See above  

>>
>> // tady uz jsou vsechna pismena mala ? ale proc vzdyt uz s
>> findfile.files[i] nepracuji ? Nepotrebuji aby to bylo male
>> potrebuji aby to bylo s originalni velikosti
>> if extractfileext(radek)='.sa' then
>> Satemp.Add(findfile.files[i])
>> else RecordTemp.Add(findfile.files[i]);
>> end;

> Najjednoduchsie bude podla mna vyhodit to volanie strlower a tu podmienku
> napisat takto:
> if SameText(ExtractFileExt(radek), '.sa') then

> kedze pre '.sa' nepotrebujes porovnavat podla locale. Inak by sa hodilo
> AnsiCompareText.

> HTH
> TOndrej




S pozdravem
  
 Milan Vymazal